package com.seeqool.v1;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

import com.seeqool.v1.datamodel.SQLTable;

public class QueryThread extends Thread {
	private boolean isBusy = false;
	private boolean wasCancelled = false;
	private Statement dbStatement = null;
	private String nextQuery;
	private QueryCallback nextCallback;
	private int nextQueryID;

	public QueryThread(String url, String username, String password, String SQL, QueryCallback callback, int queryID) throws SQLException {
		super();
		Connection dbConnection = DriverManager.getConnection(url, username, password);
		dbStatement = dbConnection.createStatement();
		nextQuery = SQL; 
		nextCallback = callback;
		nextQueryID = queryID;
		isBusy = true;
		start();
	}
	
	public synchronized void waitForQuery() {
		try {
			wait();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public void run() {
		int updates = 0;
		boolean isMore;
		while (true) {
			try {
				wasCancelled = false;
				isMore = dbStatement.execute(nextQuery);
				if (wasCancelled) {
					nextCallback.onError(nextQueryID, "Statement cancelled due to client request");
				} else {
					if (!isMore) {
						updates = dbStatement.getUpdateCount();
					}
					while (isMore || (updates>-1)) {
						if (isMore) {
							nextCallback.onResult(nextQueryID, new SQLTable(dbStatement.getResultSet()));
						} else {
							nextCallback.onUpdateCount(nextQueryID, updates);
						}
						isMore = dbStatement.getMoreResults();
						if (!isMore) updates = dbStatement.getUpdateCount();
					}
					nextCallback.onComplete(nextQueryID);
				}
			} catch (SQLException e) {
				nextCallback.onError(nextQueryID, e.getMessage());
			}
			isBusy=false;
			waitForQuery();
		}
	}
	
	public synchronized boolean execute(String SQL, QueryCallback callback, int queryID) {
		if (isBusy) return false;
		isBusy = true;
		nextQuery = SQL;
		nextCallback = callback;
		nextQueryID = queryID;
		notify();		
		return true;
	}
	
	public void cancel() throws SQLException {
		wasCancelled = true;
		dbStatement.cancel();
	}
}
